package com.sf.marathon.soul.core.base;

import java.io.Serializable;

import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.sf.marathon.soul.core.util.AssertUtils;
import com.sf.marathon.soul.core.util.ReflectUtils;

/**
 * @author 01368146<br>
 *         BaseService<br>
 *         基础服务类（ 泛型：M 是 mapper 对象，T 是实体 ， PK 是主键泛型 ）<br>
 * @since 2017/6/14<br>
 */
public abstract class BaseService<M extends BaseDao<T>, T> extends ServiceImpl {

    /**
     * <p>
     * baseDao；对于自定义的方法（除baseMapper提供的公共方法）请使用baseDao调用
     * 这里存在重复注入问题，为了不影响代码后续的升级工作，先这样处理，尽管不是很好
     * </p>
     */
    @Autowired
    protected M baseDao;

    /**
     * 获取代理服务类
     *
     * @return
     */
    protected BaseService getProxyService() {
        return (BaseService) AopContext.currentProxy();
    }

    /**
     * 保存
     *
     * @param reqData
     * @return
     */
    public String save(SaveRequest<T> reqData) {
        OperationTypeEnum opTypeEnum = OperationTypeEnum.getByValue(reqData.getOpType());
        return doSave(opTypeEnum, reqData.getData());
    }

    protected String doSave(OperationTypeEnum opTypeEnum, T data) {
        String result = "";
        if (opTypeEnum == null) {
            throw new IllegalArgumentException("保存请求中无有效的操作类型[A U D]");
        }
        // 转换bean，因范型无法自动转换
        T m = parseBean(data, currentModelClass());

        switch (opTypeEnum) {
            case ADD:
                result = getProxyService().doInsert(m);
                break;
            case UPDATE:
                result = getProxyService().doUpdate(m);
                break;
            case DELETE:
                result = getProxyService().doDelete(m);
                break;
            default: break;
        }

        return result;
    }

    /**
     * 插入 可由子类覆写
     *
     * @param m
     * @return
     */
    protected String doInsert(T m) {
        getProxyService().insert(m);
        Object id = ReflectUtils.invokeGetter(m, "id");
        return id.toString();
    }

    /**
     * 更新 可由子类覆写
     *
     * @param m
     * @return
     */
    protected String doUpdate(T m) {
        getProxyService().updateById(m);
        return "";
    }

    /**
     * 删除 可由子类覆写
     *
     * @param m
     * @return
     */
    protected String doDelete(T m) {
        Serializable id = (Serializable) ReflectUtils.invokeGetter(m, "id");
        AssertUtils.notNull(id, "删除的数据传入ID不能为空");
        getProxyService().deleteById(id);
        return "";
    }

    /**
     * 判断是否为jsonObject，若不是则转换为特定entity
     *
     * @param m
     */
    protected T parseBean(Object m, Class<?> calzz) {
        if (m instanceof JSONObject) {
            return (T) JSON.parseObject(m.toString(), calzz);
        } else {
            return (T) m;
        }
    }
}
